summaryrefslogtreecommitdiff
path: root/app/[lng]/evcp
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-10-17 08:09:35 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-10-17 08:09:35 +0000
commitbea9853efe30c393b0d030bc552c1f5bbb838835 (patch)
tree820e12543f847bbcdc8d55b575016c535fb299c6 /app/[lng]/evcp
parent1540eac291761ffd8fc1947ed626e4e4a4407922 (diff)
(대표님) 데이터룸 관련 개발사항
Diffstat (limited to 'app/[lng]/evcp')
-rw-r--r--app/[lng]/evcp/data-room/[projectId]/members/page.tsx41
-rw-r--r--app/[lng]/evcp/data-room/[projectId]/settings/page.tsx20
2 files changed, 34 insertions, 27 deletions
diff --git a/app/[lng]/evcp/data-room/[projectId]/members/page.tsx b/app/[lng]/evcp/data-room/[projectId]/members/page.tsx
index 18442c0e..dbd5e37d 100644
--- a/app/[lng]/evcp/data-room/[projectId]/members/page.tsx
+++ b/app/[lng]/evcp/data-room/[projectId]/members/page.tsx
@@ -105,7 +105,7 @@ export default function ProjectMembersPage({
const [roleFilter, setRoleFilter] = useState<string>('all');
const [addMemberOpen, setAddMemberOpen] = useState(false);
const [editingMember, setEditingMember] = useState<Member | null>(null);
-
+
// 사용자 선택 관련 상태
const [availableUsers, setAvailableUsers] = useState<User[]>([]);
const [selectedUser, setSelectedUser] = useState<User | null>(null);
@@ -113,12 +113,12 @@ export default function ProjectMembersPage({
const [userPopoverOpen, setUserPopoverOpen] = useState(false);
const [loadingUsers, setLoadingUsers] = useState(false);
const [isExternalUser, setIsExternalUser] = useState(false); // 외부 사용자 여부
-
+
const [newMemberRole, setNewMemberRole] = useState<string>('viewer');
const [currentUserRole, setCurrentUserRole] = useState<string>('viewer');
const [page, setPage] = useState(1);
const pageSize = 20;
-
+
// Command component key management
const userOptionIdsRef = useRef<Record<number, string>>({});
const popoverContentId = `popover-content-${Date.now()}`;
@@ -284,7 +284,7 @@ export default function ProjectMembersPage({
const handleSelectUser = (user: User) => {
setSelectedUser(user);
setUserPopoverOpen(false);
-
+
// 외부 사용자(partners)인 경우 역할을 viewer로 고정
if (user.domain === 'partners') {
setIsExternalUser(true);
@@ -319,6 +319,7 @@ export default function ProjectMembersPage({
user.email.toLowerCase().includes(userSearchTerm.toLowerCase())
);
+
const canManageMembers = currentUserRole === 'owner' || currentUserRole === 'admin';
const totalPages = Math.max(1, Math.ceil(filteredMembers.length / pageSize));
@@ -577,7 +578,7 @@ export default function ProjectMembersPage({
<TabsContent value="internal" className="space-y-4 mt-4">
<div className="space-y-2">
<Label htmlFor="internal-user">사용자 선택</Label>
-
+
{loadingUsers ? (
<div className="flex items-center justify-center py-4">
<Loader2 className="h-4 w-4 animate-spin" />
@@ -665,8 +666,8 @@ export default function ProjectMembersPage({
<div className="space-y-2">
<Label htmlFor="internal-role">역할</Label>
- <Select
- value={newMemberRole}
+ <Select
+ value={newMemberRole}
onValueChange={setNewMemberRole}
disabled={!selectedUser || isExternalUser}
>
@@ -685,14 +686,14 @@ export default function ProjectMembersPage({
<TabsContent value="external" className="space-y-4 mt-4">
<div className="rounded-lg bg-amber-50 border border-amber-200 p-3 mb-4">
<p className="text-sm text-amber-800">
- <strong>보안 정책 안내</strong><br/>
+ <strong>보안 정책 안내</strong><br />
외부 사용자(파트너)는 보안 정책상 Viewer 권한만 부여 가능합니다.
</p>
</div>
<div className="space-y-2">
<Label htmlFor="external-user">파트너 선택</Label>
-
+
{loadingUsers ? (
<div className="flex items-center justify-center py-4">
<Loader2 className="h-4 w-4 animate-spin" />
@@ -723,7 +724,7 @@ export default function ProjectMembersPage({
<PopoverContent className="w-[460px] p-0">
<Command>
<CommandInput
- placeholder="이름으로 검색..."
+ placeholder="이름 또는 이메일로 검색..."
value={userSearchTerm}
onValueChange={setUserSearchTerm}
/>
@@ -738,7 +739,7 @@ export default function ProjectMembersPage({
<CommandEmpty>파트너를 찾을 수 없습니다.</CommandEmpty>
<CommandGroup heading="파트너 목록">
{filteredUsers
- .filter(u => u.domain === 'partners')
+ .filter(u => u.ownerCompanyId !== null)
.map((user) => (
<CommandItem
key={user.id}
@@ -748,12 +749,14 @@ export default function ProjectMembersPage({
setIsExternalUser(true);
setNewMemberRole('viewer');
}}
- value={user.name}
+ value={`${user.name} ${user.email}`}
className="truncate"
>
- <Users className="mr-2 h-4 w-4 text-amber-600" />
- <span className="truncate flex-1">{user.name}</span>
- <Badge variant="outline" className="text-xs mx-2">파트너</Badge>
+ <Users className="mr-2 h-4 w-4 text-amber-600 flex-shrink-0" />
+ <div className="flex-1 truncate">
+ <div className="font-medium truncate">{user.name}</div>
+ <div className="text-xs text-muted-foreground truncate">{user.email}</div>
+ </div>
<Check
className={cn(
"ml-auto h-4 w-4 flex-shrink-0",
@@ -785,8 +788,8 @@ export default function ProjectMembersPage({
</Tabs>
<DialogFooter>
- <Button
- variant="outline"
+ <Button
+ variant="outline"
onClick={() => {
setAddMemberOpen(false);
setSelectedUser(null);
@@ -797,8 +800,8 @@ export default function ProjectMembersPage({
>
취소
</Button>
- <Button
- onClick={addMember}
+ <Button
+ onClick={addMember}
disabled={!selectedUser}
>
추가하기
diff --git a/app/[lng]/evcp/data-room/[projectId]/settings/page.tsx b/app/[lng]/evcp/data-room/[projectId]/settings/page.tsx
index aa0f3b52..fc132e65 100644
--- a/app/[lng]/evcp/data-room/[projectId]/settings/page.tsx
+++ b/app/[lng]/evcp/data-room/[projectId]/settings/page.tsx
@@ -2,7 +2,7 @@
// app/projects/[projectId]/settings/page.tsx
'use client';
-import { useState, useEffect } from 'react';
+import { useState, useEffect ,use} from 'react';
import {
Settings,
Shield,
@@ -59,8 +59,12 @@ interface ProjectSettings {
export default function ProjectSettingsPage({
params
}: {
- params: { projectId: string }
+ params: Promise<{ projectId: string }>
}) {
+
+ const { projectId } = use(params);
+
+
const [settings, setSettings] = useState<ProjectSettings | null>(null);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
@@ -74,12 +78,12 @@ export default function ProjectSettingsPage({
useEffect(() => {
fetchSettings();
checkUserRole();
- }, [params.projectId]);
+ }, [projectId]);
const fetchSettings = async () => {
try {
setLoading(true);
- const response = await fetch(`/api/projects/${params.projectId}/settings`);
+ const response = await fetch(`/api/projects/${projectId}/settings`);
if (!response.ok) {
throw new Error('설정을 불러올 수 없습니다');
@@ -100,7 +104,7 @@ export default function ProjectSettingsPage({
const checkUserRole = async () => {
try {
- const response = await fetch(`/api/projects/${params.projectId}/access`);
+ const response = await fetch(`/api/projects/${projectId}/access`);
const data = await response.json();
setCurrentUserRole(data.role);
} catch (error) {
@@ -113,7 +117,7 @@ export default function ProjectSettingsPage({
try {
setSaving(true);
- const response = await fetch(`/api/projects/${params.projectId}/settings`, {
+ const response = await fetch(`/api/projects/${projectId}/settings`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(settings),
@@ -138,7 +142,7 @@ export default function ProjectSettingsPage({
const deleteProject = async () => {
try {
- const response = await fetch(`/api/projects/${params.projectId}`, {
+ const response = await fetch(`/api/projects/${projectId}`, {
method: 'DELETE',
});
@@ -161,7 +165,7 @@ export default function ProjectSettingsPage({
const archiveProject = async () => {
try {
- const response = await fetch(`/api/projects/${params.projectId}/archive`, {
+ const response = await fetch(`/api/projects/${projectId}/archive`, {
method: 'POST',
});